package org.kenewstar.file.controller;

import org.kenewstar.common.bean.dto.FileAndFolderDto;
import org.kenewstar.common.bean.pojo.MicroFile;
import org.kenewstar.common.bean.pojo.MicroFolder;
import org.kenewstar.common.bean.pojo.MicroShare;
import org.kenewstar.common.bean.pojo.MicroUser;
import org.kenewstar.common.constant.CommonConstant;
import org.kenewstar.common.utils.AssertUtil;
import org.kenewstar.common.utils.CommonResult;
import org.kenewstar.common.utils.CommonUtil;
import org.kenewstar.file.dto.*;
import org.kenewstar.file.service.FileService;
import org.kenewstar.file.service.FolderService;
import org.kenewstar.file.service.ShareService;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 文件分享Controller
 * @author xinke.huang@hand-china.com
 * @version 1.0
 * @date 2021/3/10
 */
@RestController
@CrossOrigin(origins = {CommonConstant.API_HOST},allowCredentials = "true")
@RequestMapping("/share")
public class ShareController {

    @Resource
    private ShareService shareService;
    @Resource
    private FolderService folderService;
    @Resource
    private FileService fileService;

    /**
     * 创建分享链接
     * @param dto 参数
     * @param session session
     * @return result
     */
    @RequestMapping("/create")
    public CommonResult createShare(@RequestBody ShareFileParamDto dto, HttpSession session){
        AssertUtil.notNull(dto);
        // 获取用户
        MicroUser user = (MicroUser) session.getAttribute(CommonConstant.SESSION_USER);
        // 执行
        ShareUrlAndCodeDto urlAndCodeDto = shareService.createShare(dto, user.getId());
        //返回链接和提取码
        return CommonResult.success(urlAndCodeDto);
    }

    /**
     * 查询所有分享数据
     * @param session session
     * @return result
     */
    @PostMapping("/query/all")
    public CommonResult queryAllShare(HttpSession session){
        // 获取用户
        MicroUser user = (MicroUser) session.getAttribute(CommonConstant.SESSION_USER);
        // 查询所有数据
        List<ShareFileUrlDto> dtoList = shareService.queryAllShare(user.getId());
        // 返回数据列表
        return CommonResult.success(dtoList);
    }

    /**
     * 批量删除分享文件数据
     * @param ids id集合
     * @return result
     */
    @PostMapping("/delete")
    public CommonResult deleteShare(@RequestBody List<Long> ids, HttpSession session) {
        AssertUtil.notNull(ids);
        int deleted = shareService.deleteShare(ids);
        clearShareCache(session,ids.size() > 0 ? ids.get(0) : -1L);
        return CommonResult.success(deleted);
    }
    @SuppressWarnings("all")
    private void clearShareCache(HttpSession session,Long id) {
        Map<String, MicroShare> map = (Map<String, MicroShare>) session.getAttribute(CommonConstant.SESSION_SHARE);
        if (Objects.nonNull(map)) {
            for (Map.Entry<String, MicroShare> entry : map.entrySet()) {
                if (id.equals(entry.getValue().getId())) {
                    map.remove(entry.getKey());
                    break;
                }
            }
            session.setAttribute(CommonConstant.SESSION_SHARE, map);
        }
    }

    /**
     * 提取文件
     * @param dto 提取参数
     * @param session session
     * @return result
     */
    @PostMapping("/extract/file")
    @SuppressWarnings("unchecked")
    public CommonResult extractFile(@RequestBody ExtractFileDto dto, HttpSession session) {
        AssertUtil.notNull(dto);
        Map<String, MicroShare> share = new HashMap<>(1);
        // 获取分享数据
        MicroShare microShare = shareService.extractFile(dto.getUrl());
        if (Objects.equals(microShare.getShareCode(), dto.getCode())) {
            Map<String, MicroShare> map = (Map<String, MicroShare>) session.getAttribute(CommonConstant.SESSION_SHARE);
            if (Objects.isNull(map)) {
                share.put(dto.getUrl(), microShare);
                session.setAttribute(CommonConstant.SESSION_SHARE, share);
            } else {

                map.put(dto.getUrl(), microShare);
                session.setAttribute(CommonConstant.SESSION_SHARE, map);
            }
            return CommonResult.success();
        }
        return CommonResult.failed();
    }

    /**
     * 根据url 参数获取分享数据
     * @param url 参数
     * @param session session
     * @return result
     */
    @GetMapping("/query/url")
    @SuppressWarnings("unchecked")
    public CommonResult queryShareDataByUrl(String url, HttpSession session) {
        AssertUtil.notNull(url);
        Map<String, MicroShare> share = (Map<String, MicroShare>) session.getAttribute(CommonConstant.SESSION_SHARE);
        if (Objects.isNull(share)) {
            return CommonResult.failed();
        }
        MicroShare microShare = share.get(url);
        if (Objects.isNull(microShare)) {
            return CommonResult.failed();
        }
        ShareDataDto dataDto = new ShareDataDto();
        BeanUtils.copyProperties(microShare, dataDto);
        List<FileShareDto> list = CommonUtil.json2List(microShare.getShareFileList(), FileShareDto.class);
        List<FileAndFolderDto> resultList = folderService.selectFileAndFolderByIds(list);
        dataDto.setFileList(resultList);
        return CommonResult.success(dataDto);
    }

    /**
     * 保存分享文件
     * @param list 前端选中文件列表
     * @param folderId 保存至文件夹的id
     * @return result
     */
    @PostMapping("/save/share/files")
    public CommonResult saveShareFiles(@RequestBody List<FileAndFolderDto> list,
                                       Long folderId, HttpSession session) {
        MicroUser user = (MicroUser) session.getAttribute(CommonConstant.SESSION_USER);

        List<MicroFolder> folderList = new ArrayList<>();
        List<MicroFile>   fileList   = new ArrayList<>();

        Map<Long, List<MicroFolder>> folderMap = new HashMap<>();
        Map<Long, List<MicroFile>> fileMap = new HashMap<>();
        list.forEach(dto -> {
            if (Objects.equals(dto.getType(), CommonConstant.FILE)) {
                MicroFile file = new MicroFile();
                file.setFolderId(folderId);
                file.setActualId(dto.getActualId());
                file.setFileType(dto.getFileType());
                file.setFileByte(dto.getFileByte());
                file.setUserId(user.getId());
                file.setFilename(dto.getName());
                fileList.add(file);
            } else {
                MicroFolder folder = new MicroFolder();
                folder.setFolderName(dto.getName());
                folder.setParentFolderId(folderId);
                folder.setUserId(dto.getUid());
                folder.setId(dto.getId());
                folderList.add(folder);
            }
        });

        folderData(folderList, folderMap, fileMap, user.getId());
        int count = folderList.size() + fileList.size();
        for (Map.Entry<Long, List<MicroFolder>> folder : folderMap.entrySet()) {
            count += folder.getValue().size();
        }
        for (Map.Entry<Long, List<MicroFile>> folder : fileMap.entrySet()) {
            count += folder.getValue().size();
        }
        if (count > 500) {
            return CommonResult.failed("保存的文件数大于500");
        }
        // 保存操作
        return shareService.saveShareFilesAndFolders(fileList, folderList, fileMap, folderMap, user.getId());
    }

    private void folderData(List<MicroFolder> folders,
                            Map<Long, List<MicroFolder>> folderMap,
                            Map<Long, List<MicroFile>> fileMap,
                            Integer userId) {
        folders.forEach(folder -> {
            // 查询文件夹的子文件夹
            List<MicroFolder> list = folderService.selectFoldersByPid(folder.getUserId(), folder.getId());
            folderMap.put(folder.getId(), list);

            // 获取文件夹下的文件
            List<MicroFile> files = fileService.selectFilesByPid(folder.getUserId(), folder.getId());
            fileMap.put(folder.getId(), files.stream().peek(f -> f.setUserId(userId)).collect(Collectors.toList()));

            if (list.size() != 0) {
                // 递归查询子文件夹
                folderData(list, folderMap, fileMap, userId);
            }
        });
    }


}
